package com.sojson.project.service.impl;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.sojson.constant.Lock;
import com.sojson.enums.EActivityGetMethod;
import com.sojson.enums.EActivityStatus;
import com.sojson.enums.core.EActivityScopeUser;
import com.sojson.project.dao.ActivityDao;
import com.sojson.project.dao.ActivityUserDao;
import com.sojson.project.dao.CouponDao;
import com.sojson.project.dao.HelpRecordDao;
import com.sojson.project.dao.UserActivityDao;
import com.sojson.project.dao.UserCouponDao;
import com.sojson.project.entity.po.Activity;
import com.sojson.project.entity.po.ActivityUser;
import com.sojson.project.entity.po.Coupon;
import com.sojson.project.entity.po.HelpRecord;
import com.sojson.project.entity.po.UserActivity;
import com.sojson.project.entity.vo.ActivityVo;
import com.sojson.project.service.ActivityService;
import com.sojson.util.DateUtil;
import com.sojson.util.ExpUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.file.constant.ConstantFileFieldName;
import com.sojson.util.file.depot.FileDepotUtil;
import com.sojson.util.file.enums.EFileTable;
import com.sojson.util.id.IdUtil;
import com.sojson.util.param.ParamUtil;
import com.sojson.util.token.TokenUtil;

/**
 * 活动表Service实现类
 * 
 * @author liu
 * @date 2021-03-24
 */
@Service
public class ActivityServiceImpl implements ActivityService {

    @Resource
    private ActivityDao activityDaoImpl;
    @Resource
    private CouponDao couponDaoImpl;
    @Resource
    private HelpRecordDao helpRecordDaoImpl;
    @Resource
    private ActivityUserDao activityUserDaoImpl;
    @Resource
    private UserActivityDao userActivityDaoImpl;
    @Resource
    private UserCouponDao userCouponDaoImpl;

    /**
     * 单条插入
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int insert(Activity activity) {
        // 查看活动奖品是否存在
        String bindCouponNo = activity.getBindCouponNo();
        if (StringUtil.isNotBlankObject(bindCouponNo)) {
            String[] split = bindCouponNo.split(",");
            if (split.length < 1) {
                ExpUtil.throwEx("优惠券不存在！");
            }
            Integer countByNo = couponDaoImpl.countByNoArr(split);
            if (countByNo != split.length) {
                ExpUtil.throwEx("优惠券不存在！");
            }
        }

        // 如果是助力活动,查看活动开始时间是否比已有助力活动结束时间提前
        Integer getMethod = activity.getGetMethod();
        int insert = 0;
        synchronized (ActivityService.class) {
            if (EActivityGetMethod.HELP.getCode() == getMethod) {
                Date findLastHelpEndTime = activityDaoImpl.findLastHelpEndTime();
                if (StringUtil.isNotBlankObject(findLastHelpEndTime)
                    && activity.getStartTime().getTime() - findLastHelpEndTime.getTime() < 0) {
                    ExpUtil.throwEx("助力活动同时只能有一个,请确认活动开始时间是否比其他助力活动结束时间早！");
                }
            }

            insert = activityDaoImpl.insert(activity);
        }

        Integer scopeUser = activity.getScopeUser();
        List<String> userNos = activity.getUserNos();
        if (StringUtil.isNotBlankObject(scopeUser) && (EActivityScopeUser.APPOINT_SOME_YES.getCode() == scopeUser
            || EActivityScopeUser.APPOINT_SOME_NO.getCode() == scopeUser) && userNos.size() > 0) {
            ActivityUser activityUser = new ActivityUser();
            activityUser.insertInit(activity);
            int insertAll = activityUserDaoImpl.insertAll(activityUser);
            if (insertAll < 1) {
                ExpUtil.throwEx("添加失败，请重试！");
            }
        }

        if (insert > 0) {
            FileDepotUtil.insertSync(EFileTable.ACTIVITY, ConstantFileFieldName.THUMB, activity.getThumb());
        }
        return insert;
    }

    /**
     * 批量插入
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int insertList(Activity activity) {
        int insertList = activityDaoImpl.insertList(activity.getActivitys());
        return insertList;
    }

    /**
     * 通过对象批量删除(物理删除)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByDto(Activity activity) {
        int deleteByDto = activityDaoImpl.deleteByDto(activity);
        return deleteByDto;
    }

    /**
     * 统计全部数量
     * 
     * @return
     * @throws SQLException
     */
    @Override
    public int countAll() {
        int countAll = activityDaoImpl.countAll();
        return countAll;
    }

    /**
     * 查询所有
     * 
     * @return
     * @throws SQLException
     */
    @Override
    public List<Activity> findAll() {
        List<Activity> findAll = activityDaoImpl.listAll();
        return findAll;
    }

    /**
     * 根据对象统计数量
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int countByDto(Activity activity) {
        int countByDto = activityDaoImpl.countByDto(activity);
        return countByDto;
    }

    /**
     * 根据对象查询
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public List<Activity> findByDto(Activity activity) {
        List<Activity> findByDto = activityDaoImpl.listByDto(activity);
        return findByDto;
    }

    /**
     * 通过id删除(物理删除)
     * 
     * @param id
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteById(Integer id) {
        int deleteById = activityDaoImpl.deleteById(id);
        return deleteById;
    }

    /**
     * 通过id列表删除(物理删除)
     * 
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public int deleteByIdList(ArrayList<Integer> ids) {
        int deleteByIdList = activityDaoImpl.deleteByIdList(ids);
        return deleteByIdList;
    }

    /**
     * 通过id更新(全部更新)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int updateById(Activity activity) {
        int updateById = activityDaoImpl.updateById(activity);
        return updateById;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容相同)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticByIdList(Activity activity) {
        int updateStaticByIdList = activityDaoImpl.updateStaticByIdList(activity);
        return updateStaticByIdList;
    }

    /**
     * 通过id列表更新(全部更新)(更新内容不相同)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangeByIdList(Activity activity) {
        int updateChangeByIdList = activityDaoImpl.updateChangeByIdList(activity.getActivitys());
        return updateChangeByIdList;
    }

    /**
     * 通过id更新(局部更新)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int updatePartialById(Activity activity) {
        Activity findById = activityDaoImpl.findById(activity.getId());

        int updatePartialById = activityDaoImpl.updatePartialById(activity);

        if (updatePartialById > 0) {
            FileDepotUtil.updateSync(EFileTable.ACTIVITY.getCode(), ConstantFileFieldName.THUMB, activity.getThumb(),
                findById.getThumb());
        }
        return updatePartialById;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容相同)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int updateStaticPartialByIdList(Activity activity) {
        int updateStaticPartialByIdList = activityDaoImpl.updateStaticPartialByIdList(activity);
        return updateStaticPartialByIdList;
    }

    /**
     * 通过id列表更新(局部更新)(更新内容不相同)
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public int updateChangePartialByIdList(Activity activity) {
        int updateChangePartialByIdList = activityDaoImpl.updateChangePartialByIdList(activity.getActivitys());
        return updateChangePartialByIdList;
    }

    /**
     * 通过id查询
     * 
     * @param id
     * @return
     */
    @Override
    public Activity findById(String id) {
        Activity findById = activityDaoImpl.findById(id);
        return findById;
    }

    /**
     * 通过编号查询
     * 
     * @param no
     * @return
     */
    @Override
    public Activity findByNo(String no) {
        Activity findByNo = activityDaoImpl.findByNo(no);
        return findByNo;
    }

    /**
     * 通过id列表查询
     * 
     * @param ids
     * @return
     * @throws SQLException
     */
    @Override
    public ArrayList<Activity> findByIdList(ArrayList<Integer> ids) {
        ArrayList<Activity> findByIdList = activityDaoImpl.findByIdList(ids);
        return findByIdList;
    }

    /**
     * 通过对象查询id列表
     * 
     * @param activity
     * @return
     * @throws SQLException
     */
    @Override
    public ArrayList<Integer> findIdByDto(Activity activity) {
        ArrayList<Integer> findIdByDto = activityDaoImpl.findIdByDto(activity);
        return findIdByDto;
    }

    /**
     * 清空数据(物理清空)
     * 
     * @throws SQLException
     */
    @Override
    public void clear() {
        activityDaoImpl.clear();
    }

    /**
     * 获取当前时间的助力活动
     * 
     * @return
     * @throws IOException 
     * @throws Exception 
     */
    @Override
    public ActivityVo findThisHelp() throws IOException {
        // 获取当前时间内的助力活动
        ActivityVo findThisHelp = activityDaoImpl.findThisHelp(DateUtil.nowDate());
        if (StringUtil.isBlankObject(findThisHelp)) {
            return null;
        }
        // 活动编号
        String no = findThisHelp.getNo();
        // 当前登录用户的ID
        String userId = TokenUtil.getUserId();

        // 获取助力码
        findThisHelp.setHelpCode(IdUtil.helpCodeNo(no, userId));

        // 获取已领取次数
        HelpRecord param = new HelpRecord();
        param.setActivityNo(findThisHelp.getNo());
        int countByDto = helpRecordDaoImpl.countByDto(param);

        findThisHelp.setGetCount(countByDto);
        return findThisHelp;
    }

    /**
     * 活动助力
     * 
     * @param heloCode
     * @return
     * @throws IOException 
     * @throws Exception 
     */
    @Override
    public int help(String helpCode) throws IOException {
        String parseHelpCodeNo = IdUtil.parseHelpCodeNo(helpCode);
        String[] split = parseHelpCodeNo.split(",");
        // 检查助力码是否合格
        if (StringUtil.isBlankObject(split) || split.length != 2) {
            return 0;
        }
        // 被助力用户
        String userNo = split[1];
        // 助力用户
        String helpUserNo = TokenUtil.getUserId();
        // 活动编号
        String activityNo = split[0];
        // 判断助力用户和被助力用户是否相同(不能自己给自己助力)
        if (helpUserNo.equals(userNo)) {
            ExpUtil.throwEx("不能自己给自己助力！");
        }

        // 判断活动是否进行中
        Activity findByNo = findByNo(activityNo);
        if (StringUtil.isBlankObject(findByNo)) {
            ExpUtil.throwEx("活动不存在！");
        }
        activityIsUnderway(findByNo);

        synchronized (Lock.ACTIVITY_HELP) {
            // 添加助力信息
            HelpRecord param = new HelpRecord();
            param.setActivityNo(activityNo);
            param.setUserNo(userNo);
            param.setUserNoHelp(helpUserNo);
            int countByDto = helpRecordDaoImpl.countByDto(param);
            if (countByDto > 0) {
                ExpUtil.throwEx("请不要重复助力！");
            }

            // 添加助力信息
            HelpRecord helpRecord = new HelpRecord();
            helpRecord.insertInit();
            helpRecord.setActivityNo(activityNo);
            helpRecord.setUserNo(userNo);
            helpRecord.setUserNoHelp(helpUserNo);
            return helpRecordDaoImpl.insert(helpRecord);
        }
    }

    /**
     * 判断活动是否进行中
     * 
     * @param activity
     */
    @Override
    public void activityIsUnderway(Activity activity) {
        // 获取优惠券信息
        List<Coupon> findByNos = couponDaoImpl.findByNos(activity.getBindCouponNo().split(","));
        activityIsUnderway(activity, findByNos, DateUtil.nowLong());
    }

    /**
     * 判断活动是否进行中
     * 
     * @param activity
     * @param now
     */
    @Override
    public void activityIsUnderway(Activity activity, List<Coupon> coupon, long now) {
        if (EActivityStatus.YES_PUBLISH.getCode() != activity.getStatus()) {
            ExpUtil.throwEx("活动未发布！");
        }
        if (activity.getStartTime().getTime() > now) {
            ExpUtil.throwEx("活动未开始！");
        }
        if (activity.getEndTime().getTime() < now) {
            ExpUtil.throwEx("活动已结束！");
        }
        if (StringUtil.isBlankObject(coupon) || coupon.size() < 1) {
            ExpUtil.throwEx("优惠券信息不存在！");
        }
    }

    /**
     * 判断用户是否能参加活动
     * 
     * @param activity
     * @throws IOException 
     */
    @Override
    public void isCanTakePartIn(Activity activity) throws IOException {

    }

    /**
     * 判断用户是否能参加活动
     * 
     * @param coupon 
     * @param activity
     * @throws IOException 
     */
    @Override
    public void isCanTakePartIn(List<Coupon> coupon, Activity activity) throws IOException {
        // 活动编号
        String no = activity.getNo();
        // 当前用户ID
        String userNo = TokenUtil.getUserId();

        // 查询用户领取奖励次数
        UserActivity userActivity = new UserActivity();
        userActivity.setActivityNo(no);
        userActivity.setBatchNo(activity.getBatchNo());
        userActivity.setUserNo(userNo);
        int countByDto = userActivityDaoImpl.countByDto(userActivity);
        // 判断是否满足活动要求的领取次数
        if (countByDto >= activity.getJoinCount()) {
            ExpUtil.throwEx("领取次数不足！");
        }

        // 如果活动是助力活动,就查询用户助力次数
        if (EActivityGetMethod.HELP.getCode() == activity.getGetMethod()) {
            // 查询用户助力次数
            HelpRecord helpRecord = new HelpRecord();
            helpRecord.setActivityNo(no);
            int hCountByDto = helpRecordDaoImpl.countByDto(helpRecord);
            // 判断是否满足活动要求的助力次数
            if (hCountByDto < activity.getHelpCount()) {
                ExpUtil.throwEx("助力次数不满足！");
            }
        }

        Iterator<Coupon> iterator = coupon.iterator();
        while (iterator.hasNext()) {
            // 可领取的数量
            Integer number = iterator.next().getNumber();
            if (number < 1) {
                iterator.remove();
            }
        }
        if (coupon.size() < 1) {
            ExpUtil.throwEx("优惠券已领完！");
        }

        Integer scopeUser = activity.getScopeUser();
        if (scopeUser == EActivityScopeUser.APPOINT.getCode() && !activity.getUseUserNo().equals(userNo)) {
            ExpUtil.throwEx("活动仅限特定用户参加！");
        } else if (scopeUser == EActivityScopeUser.APPOINT_SOME_YES.getCode()
            || scopeUser == EActivityScopeUser.APPOINT_SOME_NO.getCode()) {
            ActivityUser activityUser = new ActivityUser();
            activityUser.setActivityNo(no);
            activityUser.setUserNo(userNo);
            countByDto = activityUserDaoImpl.countByDto(activityUser);

            if (scopeUser == EActivityScopeUser.APPOINT_SOME_YES.getCode() && countByDto < 1
                || scopeUser == EActivityScopeUser.APPOINT_SOME_NO.getCode() && countByDto > 0) {
                ExpUtil.throwEx("活动仅限特定用户参加！");
            }
        }
    }

    /**
     * 获取当前时间的活动
     * 
     * @return
     * @throws IOException 
     * @throws Exception 
     */
    @Override
    public List<ActivityVo> findThis(ActivityVo activity) throws IOException {
        activity.setThisTime(DateUtil.nowDate());

        if (ParamUtil.isLogin()) {
            activity.setUserNo(TokenUtil.getUserId());
            return activityDaoImpl.findThisByUserNo(activity);
        }
        return activityDaoImpl.findThis(activity);
    }

    /**
     * 修改过期的活动状态
     * 
     * @return
     */
    @Override
    public int updateStatusToEnd(ActivityVo activity) {
        return activityDaoImpl.updateStatusToEnd(activity);
    }

}